home *** CD-ROM | disk | FTP | other *** search
- // Copyright 1992-3 by Jon Dart. All Rights Reserved.
-
- #include "bearing.h"
- #include "util.h"
- #ifdef RANGE_CHECK
- #include <assert.h>
- #endif
- #include "beardata.h"
-
- const int RankIncr = 8; // add this to move 1 rank
-
- static inline void
- SetSquare(
- const Square sq, Square * squares, unsigned &NumSquares)
- {
- #ifdef RANGE_CHECK
- assert(sq.OnBoard());
- assert (NumSquares < Bearing::MaxBearSq);
- #endif
- squares[NumSquares++] = sq;
- }
-
- static void
- PawnMoves(const Board & board,
- const ColorType side, const Square i,
- Square * squares, unsigned &NumSquares, const Boolean attacks)
- {
- Square start, dest, dest2;
- Piece piece;
-
- if (!attacks)
- {
- start = i;
- dest = (Direction[side] > 0) ? i + RankIncr : i - RankIncr;
- if (dest.OnBoard())
- {
- piece = board[dest];
- if (piece.IsEmpty())
- {
- // 1-square pawn advance
-
- SetSquare(dest, squares, NumSquares);
- if (i.Rank(board.Side()) == 2)
- {
- dest2 = (Direction[side] > 0) ?
- dest + RankIncr : dest - RankIncr;
- if (board[dest2].IsEmpty()) // 2-square advance
- SetSquare(dest2, squares, NumSquares);
- }
- }
- }
- }
- // check for possible captures
- if (i.File() != 1)
- {
- dest = (Direction[side] > 0) ? i + (RankIncr - 1) :
- i - (RankIncr + 1);
- if (dest.OnBoard())
- {
- piece = board[dest];
- if (attacks ||
- (!piece.IsEmpty() && (piece.Color() != board.Side())))
- SetSquare(dest, squares, NumSquares);
- }
- }
- if (i.File() != 8)
- {
- dest = (Direction[side] > 0) ? i + (RankIncr + 1) :
- i - (RankIncr - 1);
- if (dest.OnBoard())
- {
- piece = board[dest];
- if (attacks ||
- (!piece.IsEmpty() && (piece.Color() != board.Side())))
- SetSquare(dest, squares, NumSquares);
- }
- }
- Square epsq = board.EnPassantSq(board.OppositeSide());
- if (!epsq.IsInvalid() && !attacks)
- {
- if ((i.File() != 8 && i + 1 == epsq) ||
- (i.File() != 1 && i - 1 == epsq))
- {
- Square dest(epsq + RankIncr * Direction[side]);
- if (board[dest].IsEmpty())
- SetSquare(dest, squares, NumSquares);
- }
- }
- }
-
- #define RBMoves(board, data, squares, NumSquares) \
- Square i; \
- while ((i = *data) != 255 && board[i].IsEmpty()) \
- { \
- SetSquare(i,squares,NumSquares); \
- ++data; \
- } \
- if (i != 255 && board[i].Color() != side) \
- SetSquare(i,squares,NumSquares) \
-
- #define RBAttacks(board, data, squares, NumSquares) \
- Square i; \
- while ((i = *data) != 255 && board[i].IsEmpty()) \
- { \
- SetSquare(i,squares,NumSquares); \
- ++data; \
- } \
- if (i != 255) \
- SetSquare(i,squares,NumSquares) \
-
- static void
- KnightMoves(
- const Board & board,
- const Square loc,
- Square * squares,
- unsigned &NumSquares,
- const Boolean attacks)
- {
- const ColorType side = board[loc].Color();
- const byte *data = KnightSquares[(int)loc];
- int i = 0;
- while (i < 8 && *data != 255)
- {
- ++i;
- Square dest(*data++);
- Piece piece = board[dest];
- if ((piece.IsEmpty() || (attacks || piece.Color() != side)))
- SetSquare(dest, squares, NumSquares);
- }
- }
-
- static void
- KingMoves(
- const Board & board,
- const Square loc,
- Square * squares,
- unsigned &NumSquares,
- const Boolean attacks)
- {
- const ColorType side = board[loc].Color();
- const byte *data = KingSquares[(int)loc];
- for (int i = 0; i <8 && *data != 255 ;i++)
- {
- Square dest(*data++);
- Piece piece = board[dest];
- if ((piece.IsEmpty() || (attacks || piece.Color() != side)))
- SetSquare(dest, squares, NumSquares);
- }
- }
-
- unsigned
- Bearing::BearSq(const Board & board,
- const Square loc, Square * squares)
- {
- unsigned NumSquares = 0;
- int j;
-
- const ColorType side = board[loc].Color();
- switch (board[loc].Type())
- {
- case Piece::Empty:
- break;
- case Piece::Pawn:
- PawnMoves(board, side,
- loc, squares, NumSquares, False);
- break;
- case Piece::Knight:
- KnightMoves(board, loc, squares, NumSquares, False);
- break;
- case Piece::Bishop:
- for (j = 0; j < 4; j++)
- {
- const byte *data = BishopSquares[loc] + (j*8);
- RBMoves(board, data, squares, NumSquares);
- }
- break;
- case Piece::Rook:
- for (j = 0; j < 4; j++)
- {
- const byte *data = RookSquares[loc] + (j*8);
- RBMoves(board, data, squares, NumSquares);
- }
- break;
- case Piece::Queen:
- for (j = 0; j < 4; j++)
- {
- const byte *data = BishopSquares[loc] + (j*8);
- RBMoves(board, data, squares, NumSquares);
- }
- for (j = 0; j < 4; j++)
- {
- const byte *data = RookSquares[loc] + (j*8);
- RBMoves(board, data, squares, NumSquares);
- }
- break;
- case Piece::King:
- KingMoves(board, loc, squares, NumSquares, False);
- break;
- case Piece::Invalid:
- break;
- }
- return NumSquares;
- }
-
- unsigned
- Bearing::Attack(const Board & board,
- const Square loc, const ColorType side,
- Square * squares,
- Boolean indirect)
- {
- #ifdef RANGE_CHECK
- assert(loc.OnBoard());
- #endif
- int index = 0;
- int i, n;
- Square square1, sq;
- Piece my_pawn(Piece::Pawn, side);
- if (side == Black)
- {
- if (board[loc].IsEmpty())
- {
- Square origin(loc-RankIncr);
- if (origin.OnBoard() &&
- board[origin] == my_pawn)
- squares[index++] = origin;
- if (loc.Rank(side) == 4 && board[origin].IsEmpty() &&
- board[origin - RankIncr] == my_pawn)
- squares[index++] = origin - RankIncr;
- }
- else if (loc.Rank(side) != 1)
- {
- // square is occupied, try pawn captures
- if (loc.File() != 1 &&
- board[loc - (RankIncr+1)] == my_pawn)
- squares[index++] = loc - (RankIncr+1);
- if (loc.File() != 8 &&
- board[loc - (RankIncr-1)] == my_pawn)
- squares[index++] = loc - (RankIncr-1);
- }
- }
- else
- {
- if (board[loc].IsEmpty())
- {
- Square origin(loc+RankIncr);
- if (origin.OnBoard() &&
- board[origin] == my_pawn)
- squares[index++] = origin;
- if (loc.Rank(side) == 4 && board[origin].IsEmpty() &&
- board[origin + RankIncr] == my_pawn)
- squares[index++] = origin + RankIncr;
- }
- else if (loc.Rank(side) != 1)
- {
- if (loc.File() != 8 &&
- board[loc + RankIncr+1] == my_pawn)
- squares[index++] = loc + RankIncr + 1;
- if (loc.File() != 1 &&
- board[loc + RankIncr-1] == my_pawn)
- squares[index++] = loc + RankIncr - 1;
- }
- }
- Piece knight(Piece::Knight, side);
- Piece king(Piece::King, side);
- for (i = 0; i < 8; i++)
- {
- sq = KnightSquares[loc][i];
- if (sq == 255)
- break;
- if (board[sq] == knight)
- squares[index++] = sq;
- }
- for (i = 0; i <8; i++)
- {
- sq = KingSquares[loc][i];
- if (sq == 255)
- break;
- if (board[sq] == king)
- squares[index++] = sq;
- }
- n = index;
- int offset;
- Piece bishop(Piece::Bishop, side);
- Piece queen(Piece::Queen, side);
- Piece rook(Piece::Rook, side);
- Boolean found;
- for (i = 0; i < 4; i++)
- {
- square1 = loc;
- found = False;
- offset = 0;
- const byte *data = BishopSquares[loc] + (8*i);
- while (*data != 255)
- {
- Piece piece;
- do
- {
- if (*data == 255) break;
- square1 = *data++;
- piece = board[square1];
- } while (piece.IsEmpty());
- if (piece == bishop || piece == queen)
- {
- found = True;
- ++n;
- squares[index+offset] = square1;
- if (indirect)
- offset += Bearing::Offset;
- else
- break;
- }
- else
- break;
- }
- if (found)
- ++index;
- data = RookSquares[loc] + (8*i);
- square1 = loc;
- offset = 0;
- found = False;
- for (;;)
- {
- Piece piece;
- do
- {
- if (*data == 255)
- break;
- square1 = *data++;
- piece = board[square1];
- } while (piece.IsEmpty());
- if (piece == rook || piece == queen)
- {
- found = True;
- ++n;
- squares[index+offset] = square1;
- if (indirect)
- offset += Bearing::Offset;
- else
- break;
- }
- else
- break;
- }
- if (found)
- ++index;
- }
- return n;
- }
-
- unsigned
- Bearing::Attack_or_Defend(const Board & board, const Square & loc,
- Square * squares)
- {
- unsigned NumSquares = 0;
- int j;
-
- switch (board[loc].Type())
- {
- case Piece::Empty:
- break;
- case Piece::Pawn:
- PawnMoves(board, board[loc].Color(),
- loc, squares, NumSquares, True);
- break;
- case Piece::Knight:
- KnightMoves(board, loc, squares, NumSquares, True);
- break;
- case Piece::Bishop:
- for (j = 0; j < 4; j++)
- {
- const byte *data = BishopSquares[loc] + (j*8);
- RBAttacks(board, data, squares, NumSquares);
- }
- break;
- case Piece::Rook:
- for (j = 0; j < 4; j++)
- {
- const byte *data = RookSquares[loc] + (j*8);
- RBAttacks(board, data, squares, NumSquares);
- }
- break;
- case Piece::Queen:
- for (j = 0; j < 4; j++)
- {
- const byte *data = BishopSquares[loc] + (j*8);
- RBAttacks(board, data, squares, NumSquares);
- }
- for (j = 0; j < 4; j++)
- {
- const byte *data = RookSquares[loc] + (j*8);
- RBAttacks(board, data, squares, NumSquares);
- }
- break;
- case Piece::King:
- KingMoves(board, loc, squares, NumSquares, True);
- break;
- case Piece::Invalid:
- break;
- }
- return NumSquares;
- }
-
- Boolean Bearing::Pinned( const Board &board, const Square loc,
- Piece &PinnedByPiece,
- Square &PinnedBySquare,
- int &dir)
- {
- Piece p = board[loc];
- if (p.IsEmpty() || p.Type() == Piece::King)
- return False;
- const ColorType side = p.Color();
- const ColorType oside = OppositeColor(side);
- // We "cheat" on constness by altering board[loc]. But we will
- // put the original contents back .. honest
- Piece &place = (Piece &)board[loc];
- place = Piece::EmptyPiece(); // imagine me gone
- Square ks(board.KingPos(side));
- int offset = (int)loc - (int)ks;
- int signOfOffset = Util::Sign(offset);
- if (ks.File() == loc.File()) // possible pin on file
- {
- const byte *data
- = (signOfOffset > 0) ? RookSquares[loc] + 8
- : RookSquares[loc];
- Square newsquare;
- Piece attackPiece;
- while (*data != 255)
- {
- newsquare = *data++;
- attackPiece = board[newsquare];
- if (!attackPiece.IsEmpty())
- break;
- }
- if (attackPiece.Color() == oside && (
- (attackPiece.Type() == Piece::Rook) ||
- (attackPiece.Type() == Piece::Queen)))
- {
- place = p; // put piece back
- PinnedBySquare = newsquare;
- PinnedByPiece = attackPiece;
- dir = ((int)newsquare - (int)loc > 0) ? RankIncr : -RankIncr;
- return True;
- }
- }
- if (ks.Rank(White) == loc.Rank(White)) // possible pin on rank
- {
- const byte *data = (signOfOffset > 0) ?
- RookSquares[loc]+16 : RookSquares[loc]+24;
- Square newsquare;
- Piece attackPiece;
- while (*data != 255)
- {
- newsquare = *data++;
- attackPiece = board[newsquare];
- if (!attackPiece.IsEmpty())
- break;
- }
- if (attackPiece.Color() == oside && (
- (attackPiece.Type() == Piece::Rook) ||
- (attackPiece.Type() == Piece::Queen)))
- {
- place = p; // put piece back
- PinnedBySquare = newsquare;
- PinnedByPiece = attackPiece;
- dir = ((int)newsquare > (int)loc) ? 1 : -1;
- return True;
- }
- }
- if (offset % 9 == 0) // possible diagonal pin
- {
- const byte *data
- = (signOfOffset > 0) ? BishopSquares[loc] + 16
- : BishopSquares[loc] + 8;
- Square newsquare;
- Piece attackPiece;
- while (*data != 255)
- {
- newsquare = *data++;
- attackPiece = board[newsquare];
- if (!attackPiece.IsEmpty())
- break;
- }
- if (attackPiece.Color() == oside && (
- (attackPiece.Type() == Piece::Bishop) ||
- (attackPiece.Type() == Piece::Queen)))
- {
- place = p; // put piece back
- PinnedBySquare = newsquare;
- PinnedByPiece = attackPiece;
- dir = ((int)newsquare > (int)loc) ? 9 : -9;
- return True;
- }
- }
- if (offset % 7 == 0) // possible diagonal pin
- {
- const byte *data
- = (signOfOffset > 0) ? BishopSquares[loc] + 24
- : BishopSquares[loc];
- Square newsquare;
- Piece attackPiece;
- while (*data != 255)
- {
- newsquare = *data++;
- attackPiece = board[newsquare];
- if (!attackPiece.IsEmpty())
- break;
- }
- if (attackPiece.Color() == oside && (
- (attackPiece.Type() == Piece::Bishop) ||
- (attackPiece.Type() == Piece::Queen)))
- {
- place = p; // put piece back
- PinnedBySquare = newsquare;
- PinnedByPiece = attackPiece;
- dir = ((int)newsquare > (int)loc) ? 7 : -7;
- return True;
- }
- }
- place = p;
- return False;
- }
-
-